<!--
详见： https://blog.csdn.net/qq_41463655/article/details/124768421
 -->

<template>
    <div id="vue-tinymce">
        <vue-tinymce ref="tinymce"  :setup="setUp" v-model="editorValue" :setting="setting"/>
    </div>
</template>

<script>
import request from "@/router/axios";
import {proxyPath} from "@/config/env";
export default {
    name: 'vueTinymceEditor',
    data() {
        return {
            editorValue: this.content != null ? this.content : "",
            setting: {
                menubar: true,  // 菜单栏
                //inline: true,   //开启内联模式
                toolbar:
                    "insertimage | undo redo | fullscreen | formatselect alignleft aligncenter alignright alignjustify | link unlink | numlist bullist | image media table emoticons | fontselect fontsizeselect forecolor backcolor | bold italic underline strikethrough | indent outdent | superscript subscript | removeformat | wordcount code",
                toolbar_drawer: "sliding",
                quickbars_selection_toolbar: "removeformat | bold italic underline strikethrough | fontsizeselect forecolor backcolor",
                plugins: "link image media table lists fullscreen quickbars wordcount paste emoticons code",
                language: 'zh_CN',
                valid_elements: "*[*]", // 允许所有标签和元素
                height: 350,
                // contextmenu: 'customMenu link image',
                contextmenu: 'table | link image customMenu',
                // 图片上传地址(自动上传)
                // images_upload_url: uploadPath + 'image/vueTinymce/',
                // 允许粘贴图片上传,及格式
                paste_data_images: true,
                // paste_as_text: true,
                // images_file_types: 'jpeg,jpg,png,gif,bmp,webp',
                // 插入链接在这里处理url，确保斜线不被移除
                urlconverter_callback: function (url, node, on_save) {
                    return url;
                },
                // 此处为图片上传处理函数 (手动上传)
                images_upload_handler: (blobInfo, success, failure, progress) => {
                    console.debug('上传处理器111：');
                    // const formData = new FormData()
                    // formData.append('file', blobInfo.blob(), blobInfo.filename());
                    let file = new window.File([blobInfo.blob()], blobInfo.filename());
                    console.log(blobInfo);
                    this.crud.upload(file, "image/vueTinymce/").then(res => {
                        // 获取返回数据
                        let data = res.data.data;
                        // 添加图片到内容
                        success(data.url, data.name)
                    });
                },
                file_picker_callback: function (callback, value, meta) {
                    // Provide file and text for the link dialog
                    if (meta.filetype == 'file') {
                        callback('mypage.html', {text: 'My text'});
                    }
                    // Provide image and alt text for the image dialog
                    if (meta.filetype == 'image') {
                        callback('myimage.jpg', {alt: 'My alt text'});
                    }
                    // Provide alternative source and posted for the media dialog
                    if (meta.filetype == 'media') {
                        callback('movie.mp4', {source2: 'alt.ogg', poster: 'image.jpg'});
                    }
                },
            }
        }
    },
    methods: {
        setUp(editor) {
            editor.on('paste', (event) => {
                // 自定义粘贴
                let clipboardData = event.clipboardData;
                let files = clipboardData.items
                let bool = false;
                for (let i = 0; i < files.length; i++) {
                    if (files[i].kind === 'file' && files[i].type.match(/image\//)) {
                        event.preventDefault()
                        bool = true
                        const blob = files[i].getAsFile();
                        this.crud.upload(blob, "image/vueTinymce/").then(res => {
                            let data = res.data.data;
                            this.$refs.tinymce.editor.insertContent(`<img  src="${data.url}"  alt="${data.name}" />`);
                        })
                    } else {
                        bool = false
                    }
                }
                if (!bool) {
                    var htmlData = clipboardData.getData('text/html');
                    var parser = new DOMParser();
                    var htmlDoc = parser.parseFromString(htmlData, 'text/html');
                    var imgElements = htmlDoc.querySelectorAll('img');
                    if (imgElements.length !== 0) {
                        event.preventDefault()
                        imgElements.forEach(async (item, index) => {
                            let src = item.src
                            let file
                            if (src.startsWith('file:') || src.startsWith('blob:')) {
                                file = await this.localfile(item)
                            } else {
                                file = await this.downloadImageAsFile(src)
                            }
                            let res = await this.crud.upload(file, "image/vueTinymce/")
                            let data = res.data.data;
                            item.src = data.url
                            item.alt = data.name
                            if (index == imgElements.length - 1) {
                                this.$refs.tinymce.editor.insertContent(htmlDoc.body.innerHTML);
                            }
                        })
                    }
                }
            });
            editor.ui.registry.addMenuItem('customMenu', {
                text: '图片重命名',
                onAction: (api) => {
                    const selectedContent = editor.selection.getContent();
                    const parser = new DOMParser();
                    const doc = parser.parseFromString(selectedContent, 'text/html');
                    const imgNodes = doc.body.childNodes;
                    if (imgNodes.length == 0) {
                        editor.windowManager.alert('请选择图片')
                        return false
                    }
                    const tagName = imgNodes[0].tagName
                    if (tagName === 'IMG') {
                        let src = imgNodes[0].getAttribute('src')
                        let oldname = src.split('/')[src.split('/').length - 1]
                        editor.windowManager.open({
                            title: '图片重命名',
                            body: {
                                type: 'panel',
                                items: [
                                    {
                                        type: 'input',
                                        name: 'url',
                                        label: '地址',
                                        disabled: true,
                                    }, {
                                        type: 'input',
                                        name: 'newFileName',
                                        label: '图片名称',
                                    }
                                ]
                            },
                            buttons: [
                                {
                                    type: 'submit',
                                    text: '提交'
                                },
                                {
                                    type: 'cancel',
                                    text: '关闭',
                                },
                            ],
                            initialData: {
                                url: src, newFileName: oldname
                            },
                            onSubmit: (api) => {
                                let data = api.getData()
                                if (oldname == data.newFileName) {
                                    editor.windowManager.alert('图片名未修改')
                                    return false
                                }
                                downloadUpload(data).then(res => {
                                    if (res.data.code == 200) {
                                        imgNodes[0].setAttribute('src', res.data.data)
                                        editor.selection.setContent(doc.body.innerHTML);
                                        api.close();
                                    } else {
                                        editor.windowManager.alert('图片名修改失败')
                                    }
                                })
                            },
                        });
                    } else {
                        editor.windowManager.alert('该预设只能应用于图片')
                    }
                },
            });
        },
        async localfile(imgElement) {
            return new Promise((resolve, reject) => {
                const canvas = document.createElement('canvas');
                canvas.width = imgElement.naturalWidth;
                canvas.height = imgElement.naturalHeight;
                const ctx = canvas.getContext('2d');
                ctx.drawImage(imgElement, 0, 0);
                const fileName = imgElement.src.split('/').pop();
                // 从 canvas 获取 Blob 数据
                canvas.toBlob(blob => {
                    resolve(new File([blob], fileName, {type: 'image/jpeg'}));
                }, 'image/jpeg');
            });
        },
        downloadImageAsFile(url) {
            return new Promise((resolve, reject) => {
                var xhr = new XMLHttpRequest();
                xhr.open('GET', url, true);
                xhr.responseType = 'blob'; // 设置响应类型为 Blob

                xhr.onload = function () {
                    if (xhr.status === 200) {
                        // 成功获取 Blob 数据
                        const fileName = url.split('/').pop();
                        var blob = xhr.response;
                        var file = new File([blob], fileName, {type: 'image/jpeg'});
                        console.log(file, 'down');
                        resolve(file)
                    } else {
                        // 请求失败
                        reject(new Error('Failed to load image'))
                    }
                };
                xhr.onerror = function () {
                    // 网络错误
                    return new Error('Network error')
                };
                xhr.send(); // 发送请求
            });
        },
    },
    props: {
        // 接收值父组件传递值
        content: String
    },
    created() {
        console.debug("--------加载 vue-tinymce 富文本编辑器")
    },
    watch: {
        editorValue: {
            handler(newNum, oldNum) {

                // 修改调用者传入的值
                this.$emit('update:content', newNum)
            },
            deep: true
        }
    }
}

// 下载上传
function  downloadUpload(data) {
    return request({
        url: proxyPath + `/api/open/file/downloadUpload?newFileName=${data.newFileName}&url=${data.url}`,
        method: 'put',
    })
}
</script>

<style>
/* 富文本按钮功能优先级,最好 > 2500  弹出默认2000+ */
.tox-tinymce-aux {
    z-index: 9999 !important;
}
</style>